package util;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import server.HttpServlet;
import server.Request;
import server.Servlet;
import webresources.Context;
import webresources.Host;
import webresources.Mapper;
import webresources.Wrapper;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.Socket;
import java.util.List;

public class ServletUtil {

    /**
     * 加载解析 server.xml web.xml，初始化Servlet
     * @param classLoader 类加载器
     * @return
     */
    public static Mapper loadServlet(ClassLoader classLoader) throws Exception {
        InputStream serverStream = null;
        InputStream resourceAsStream = null;
        Mapper mapper = new Mapper();
        try {
            // 加载配置文件 server.xml
            serverStream = classLoader.getResourceAsStream("server.xml");
            if (serverStream == null) {
                throw new Exception("未找到server.xml配置文件");
            }
            SAXReader saxReader = new SAXReader();
            Document serverDocument = new SAXReader().read(serverStream);
            Element serverRootElement = serverDocument.getRootElement();
            List<Element> services = serverRootElement.selectNodes("Service");
            for (Element service : services) {
                Host host = new Host();
                Element connector = (Element)service.selectSingleNode("Connector");
                // 监听端口号
                String port = connector.attribute("port").getValue();
                mapper.setPort(port);
                Element engineElement = (Element)service.selectSingleNode("Engine");
                Element hostElement = (Element)engineElement.selectSingleNode("host");
                String hostName = hostElement.attribute("name").getValue();
                // 获取项目所在目录
                String appBasePath = hostElement.attribute("appBase").getValue();
                File appBaseDir = new File(appBasePath);
                String[] directors = appBaseDir.list();
                Context context = new Context();
                for (String director : directors) {
                    // 加载配置文件 web.xml
                    File file = new File(appBasePath + "/" + director + "/web.xml");
                    resourceAsStream = new FileInputStream(file);
                    Document webDocument = saxReader.read(resourceAsStream);
                    Element webRootElement = webDocument.getRootElement();
                    List<Element> servletNodes = webRootElement.selectNodes("//servlet");
                    Wrapper wrapper = new Wrapper();
                    for (Element servletElement : servletNodes) {
                        // <servlet-name>lagou</servlet-name>
                        Element servletNameElement = (Element)servletElement.selectSingleNode("servlet-name");
                        String servletName = servletNameElement.getStringValue();
                        // <servlet-class>servlet.LagouServlet</servlet-class>
                        Element servletClassElement = (Element)servletElement.selectSingleNode("servlet-class");
                        String servletClass = servletClassElement.getStringValue();
                        // webapps/demo1/server/LagouServlet.class
                        String servletPath = appBasePath + "/" + director + "/" + servletClass.replaceAll("\\.","/") + ".class";
                        String name = director + "." + servletClass;
                        Class<?> aClass = MyClassLoader.newInstance().loadClass(servletPath, name);
                        HttpServlet servlet = (HttpServlet)aClass.getDeclaredConstructor().newInstance();
                        // 根据servlet-name的值找到url-pattern
                        Element servletMapping = (Element) webRootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                        String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue().replaceAll("/","");
                        wrapper.setServlet(urlPattern, servlet);
                    }
                    context.setWrapper(director, wrapper);
                }
                host.setContext(hostName, context);
                mapper.setMapper(port, host);
            }
        } finally {
            if (serverStream != null) {
                try {
                    serverStream.close();
                } catch (Exception e) {
                }
            }
            if (resourceAsStream != null) {
                try {
                    resourceAsStream.close();
                } catch (Exception e) {
                }
            }
        }
        return mapper;
    }

    /**
     * 查找servlet
     * @param request
     * @param socket
     * @param mapper
     * @return
     */
    public static Servlet queryServlet(Request request, Socket socket, Mapper mapper){
        Servlet servlet = null;
        String port = request.getPort();
        if (port == null || port.equals("")) {
            port = String.valueOf(socket.getLocalPort());
        }
        Host host = mapper.getHost(port);
        if(host != null) {
            String hostName = request.getHost();
            if (hostName == null || hostName.equals("")) {
                hostName = socket.getInetAddress().getHostAddress();
            }
            if ("127.0.0.1".equals(hostName) || "0:0:0:0:0:0:0:1".equals(hostName)) {
                hostName = "localhost";
            }
            // 动态资源servlet请求
            Context context = host.getContext(hostName);
            if (context != null) {
                String requestUrl = request.getUrl().substring(1);
                String[] urls = requestUrl.split("/",2);
                if (urls.length == 2) {
                    Wrapper wrapper = context.getWrapper(urls[0]);
                    if (wrapper != null) {
                        servlet = wrapper.getServlet(urls[1]);
                    }
                }
            }
        }
        return servlet;
    }
}
